﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Epic.Net
{
    public class AbandonBufferWriter
    {
        public AbandonBufferWriter()
        {
            this.Collection = new List<byte[]>();
            this.EnsureCapacity();
        }

        const int BufferSize = 10;

        List<byte[]> Collection
        {
            get;
            set;
        }

        byte[] Last
        {
            get { return this.Collection[this.Collection.Count - 1]; }
        }

        public int Current
        {
            get;
            private set;
        }

        public long Position
        {
            get;
            private set;
        }

        bool IsOverflow(int length)
        {
            return this.Current + length > BufferSize;

        }

        public void Write(params byte[] value)
        {
            if (!this.IsOverflow(value.Length))
            {
                System.Buffer.BlockCopy(value, 0, this.Last, this.Current, value.Length);
                this.Current += value.Length;
                this.Position += value.Length;
                return;
            }

            int remind = value.Length,
                offset = 0,
                space = 0;
            do
            {
                space = BufferSize - this.Current;
                if (remind > space)
                {
                    System.Buffer.BlockCopy(value, offset, this.Last, this.Current, BufferSize - this.Current);
                    offset += space;
                    remind -= BufferSize;
                    this.EnsureCapacity();
                }
                else
                {
                    System.Buffer.BlockCopy(value, offset, this.Last, this.Current, remind);
                    this.Current += remind;
                    remind = 0;

                }
            } while (remind > 0);

            this.Position += value.Length;


        }

        void EnsureCapacity()
        {
            this.Current = 0;
            this.Collection.Add(new byte[BufferSize]);
        }

        byte[] ArrayJoin(params byte[][] value)
        {
            var result = new byte[value.Sum(e => e.Length)];
            var offset = 0;
            for (int i = 0; i < value.Length; i++)
            {
                System.Buffer.BlockCopy(value[i], 0, result, offset, value[i].Length);
                offset += value[i].Length;

            }
            return result;
        }

        public byte[] GetBuffer()
        {
            var result = new byte[this.Position];
            var offset = 0;
            var i = 1;
            this.Collection.ForEach(e =>
            {
                System.Buffer.BlockCopy(e, 0, result, offset, i == this.Collection.Count ? (int)(this.Position - offset) : e.Length);
                i++;
                offset += e.Length;
            });

            return result;

        }


    }
}
